﻿using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MyDomain.Api;
using Newtonsoft.Json;

namespace MyApi.Controllers.File
{ 
    /// <inheritdoc />
    /// <summary>
    /// 文件服务器
    /// </summary>
    [Produces("application/json")]
    [Route("api/Files")]
    public class FilesController : Controller
    {
        private readonly IHostingEnvironment _host;

        public FilesController(IHostingEnvironment host)
        {
            _host = host;
        }

        /// <summary>
        /// 上传文件
        /// </summary> 
        /// <returns></returns>
        [HttpPost]
        [Route("uploadfile")]
        public object UploadFile()
        {
            IFormFileCollection files = Request?.Form?.Files;
            if (files == null || files.Count < 1)
                return "上传失败，文件为空！";

            List<string> name = new List<string>();
            foreach (var file in files)
            {
                if (file.Length > 0)
                {
                    string path = FilePath(file.ContentType);
                    if (!Directory.Exists(path))
                        Directory.CreateDirectory(path);

                    string filename = FileName(file.FileName);
                    using (FileStream stream = new FileStream(path + filename, FileMode.Create))
                    {
                        file.CopyTo(stream);
                        stream.Flush();
                        stream.Close();
                        name.Add(filename);
                    }
                }
            }

            return name;
        }

        /// <summary>
        /// 上传json
        /// </summary> 
        /// <returns></returns>
        [HttpPost]
        [Route("uploadjson")]
        public object UploadJson()
        {
            if (Request.Body == null || Request.ContentLength < 1)
                return "上传失败，文件为空！";

            var json = new StreamReader(Request.Body).ReadToEnd();

            Posts p = JsonConvert.DeserializeObject<Posts>(json);
            if (string.IsNullOrWhiteSpace(p?.filename) || p.b == null || p.b.Length < 1)
                return "上传失败，上传对象异常！";

            string path = FilePath(p.filename);
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            string filename = FileName(p.filename);
            using (FileStream stream = new FileStream(path + filename, FileMode.Create))
            {
                stream.Write(p.b, 0, p.b.Length);
                stream.Flush();
                stream.Close();
            }

            return Request.Host.Value + "/upload/" + FileType(p.filename) + "/" + filename;
        }

        /// <summary>
        /// 上传byte,必须利用Read缓冲区读取
        /// </summary> 
        /// <returns></returns>
        [HttpPost]
        [Route("uploadbyte")]
        public string UploadByte()
        {
            if (Request.Body == null || Request.ContentLength < 1)
                return "上传失败，文件为空！";

            string filetype = Request.Query["FileType"];
            if (string.IsNullOrWhiteSpace(filetype))
                return "上传失败，缺少文件类型！";

            string path = FilePath(filetype);
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            string filename = FileName(filetype);
            byte[] temp = new byte[1024];
            using (Stream write = new FileStream(path + filename, FileMode.Create))
            {
                int len;
                while ((len = Request.Body.Read(temp, 0, temp.Length)) > 0)
                {
                    write.Write(temp, 0, len);
                }

                write.Flush();
                write.Close();
            }
             
            return Request.Host.Value + "/upload/image/" + filename;
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <returns></returns>
        [HttpGet]
        [Route("downloadfile")]
        public FileResult DownFile(string filename)
        {
            string path = FilePath(filename);
            if (!System.IO.File.Exists(path))
                return File(new byte[0], "application/octet-stream", "文件不存在!");

            FileStream f = new FileStream(path, FileMode.Open);
            int len = Convert.ToInt32(f.Length);
            byte[] b = new byte[len];
            f.Read(b, 0, len);   //11
            return File(b, "application/octet-stream", filename);
        }

        /// <summary>
        /// 下载字节
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <returns></returns>
        [HttpGet]
        [Route("downloadbyte")]
        public byte[] DownByte(string filename)
        {
            string path = FilePath(filename);
            if (!System.IO.File.Exists(path))
                return new byte[0];

            FileStream f = new FileStream(path, FileMode.Open);
            int len = Convert.ToInt32(f.Length);
            byte[] b = new byte[len];
            f.Read(b, 0, len);
            return b;
        }

        /// <summary>
        /// 下载流
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <returns></returns>
        [HttpGet]
        [Route("downloadstream")]
        public Stream DownStream(string filename)
        {
            string path = FilePath(filename);
            if (!System.IO.File.Exists(path))
                return null;

            Stream stream = new FileStream(path, FileMode.Open);
            return stream;
        }

        /// <summary>
        /// 生成文件目录
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public string FilePath(string filename)
        {
            return _host.ContentRootPath + "\\wwwroot\\upload\\" + FileType(filename) + "\\";
        }

        /// <summary>
        /// 生成文件名
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public string FileName(string filename)
        {
            return DateTime.Now.ToString("yyyyMMddHHmmssfffffff") + FilePostfix(filename);
        }

        /// <summary>
        /// 获取文件后缀
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public string FilePostfix(string filename)
        {
            int postion = filename.LastIndexOf(".");
            return postion > 0 ? filename.Substring(postion) : "";
        }

        /// <summary>
        /// 根据mine-type或后缀获取文件类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public string FileType(string type)
        {
            if (string.IsNullOrWhiteSpace(type))
                return "other";

            type = type.ToLower();

            if (type.Contains("image") || type.Contains("jpg") || type.Contains("jpeg") || type.Contains("png") ||
                type.Contains("gif") || type.Contains("bmp"))
                return "image";
            if (type.Contains("text") || type.Contains("txt") || type.Contains("cs") || type.Contains("info") ||
                type.Contains("log") || type.Contains("config"))
                return "file";
            if (type.Contains("html") || type.Contains("htm"))
                return "html";
            if (type.Contains("xml") || type.Contains("xmls"))
                return "xml";
            if (type.Contains("json") || type.Contains("jsonp"))
                return "json";
            if (type.Contains("pdf"))
                return "pdf";
            if (type.Contains("zip"))
                return "zip";
            if (type.Contains("msdownload") || type.Contains("exe"))
                return "exe";
            return "other";
        }
    }
}